package jobscheduling.algorithms.pso;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jobscheduling.algorithms.ResultListener;

public class Swarm {
	
	private double w;
	private double c1;
	private double c2;
	private double vmax;
	
	private ResultListener resList = null;
	private int partNo;
	private Evaluator ev;
	
	private List<Particle> particleList = new ArrayList<Particle>();
	
	private int[][] bestSolution = null;
	
	
	public Swarm(ResultListener resList, int jobsNo, int partNo, Evaluator ev,
			double w, double c1, double c2, double vmax) {
		
		this.resList = resList;
		this.partNo = partNo;
		this.ev = ev;	
		this.w = w;
		this.c1 = c1;
		this.c2 = c2;
		this.vmax = vmax;
		
		/*generuje początkowe, losowe cząstki*/
		List<Integer> l = new ArrayList <Integer> (jobsNo + 1);
		for(int i = 0; i < jobsNo; i++) {
			l.add(i);
		}
		
		for(int i = 0; i < partNo; i++) {
			Collections.shuffle(l);
			particleList.add(new Particle(l, jobsNo));
		}
	}
	
	public int[] seekSolution(int iterations) {
		
		int g = 0;	//g to numer cząstki która posiada najlepsze rozwiązanie

		/*każda cząstka przechowuje swoje nakjlepsze dotychczasowe rozwiazanie!*/
		for(int i=0; i<partNo; i++)
			particleList.get(i).setCurrentSolutionAsBest();
		
		/*rój przechowuje najlepsze globalne rozwiązanie (gbest)*/
		bestSolution = particleList.get(0).copyBestSolution();
		
		Particle currentParticle = null;
		for(int i=0; i<iterations; i++) {
			
			//sprawdź czy nowe rozwiazanie jest lepsze
			for(int j=0; j<partNo; j++)
			{
				currentParticle = particleList.get(j);
				if(ev.compare(currentParticle.jobPositions, currentParticle.bestSolution)) {
					currentParticle.setCurrentSolutionAsBest();
				}
			}
			
			
			g=0;	//znajdż najlepsze globalne rozwiąznie
			for(int j=0; j<partNo; j++)
			{
				if(ev.compare(particleList.get(j), particleList.get(g)))
					g=j;
			}
			if(ev.compare(particleList.get(g).jobPositions, bestSolution))	//porównaj najlepsze obecne rozwiązanie z poprzednim najleszym
				bestSolution = particleList.get(g).copyBestSolution();
		
			
			for(int j=0; j< partNo; j++)	//aktualizuj predkości
			{
				particleList.get(j).updateVelocity(w, c1, c2, vmax, bestSolution);
			}
			
			for(int j=0; j<partNo; j++)		//konstruuj nowe możliwe rozwiązania
			{
				particleList.get(j).constructNewSolution(bestSolution, ev);
				//resList.newResult(ev.convertIntoSolution(particleList.get(j).jobPositions), ev.eval(particleList.get(j).jobPositions));
			}
			//System.out.println();
			
			if (resList != null)
				resList.newResult(ev.convertIntoSolution(bestSolution), ev.eval(bestSolution));
				//resList.newResult(ev.convertIntoSolution(particleList.get(0).bestSolution), ev.eval(particleList.get(0).bestSolution));
			//System.out.println();
		}
		
		return ev.convertIntoSolution(bestSolution);
	}
}